home *** CD-ROM | disk | FTP | other *** search
/ PC/CD Gamer UK 120 / CD Gamer Issue 120 (March 2003) (Disc 2).ISO / mods / Q2_Codered / codeRED1_0.exe / Data1.cab / cl_cin.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-08-15  |  13.1 KB  |  652 lines

  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. #include "client.h"
  21.  
  22. typedef struct
  23. {
  24.     byte    *data;
  25.     int        count;
  26. } cblock_t;
  27.  
  28. typedef struct
  29. {
  30.     qboolean    restart_sound;
  31.     int        s_rate;
  32.     int        s_width;
  33.     int        s_channels;
  34.  
  35.     int        width;
  36.     int        height;
  37.     byte    *pic;
  38.     byte    *pic_pending;
  39.  
  40.     // order 1 huffman stuff
  41.     int        *hnodes1;    // [256][256][2];
  42.     int        numhnodes1[256];
  43.  
  44.     int        h_used[512];
  45.     int        h_count[512];
  46. } cinematics_t;
  47.  
  48. cinematics_t    cin;
  49.  
  50. /*
  51. =================================================================
  52.  
  53. PCX LOADING
  54.  
  55. =================================================================
  56. */
  57.  
  58.  
  59. /*
  60. ==============
  61. SCR_LoadPCX
  62. ==============
  63. */
  64. void SCR_LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height)
  65. {
  66.     byte    *raw;
  67.     pcx_t    *pcx;
  68.     int        x, y;
  69.     int        len;
  70.     int        dataByte, runLength;
  71.     byte    *out, *pix;
  72.  
  73.     *pic = NULL;
  74.  
  75.     //
  76.     // load the file
  77.     //
  78.     len = FS_LoadFile (filename, (void **)&raw);
  79.     if (!raw)
  80.         return;    // Com_Printf ("Bad pcx file %s\n", filename);
  81.  
  82.     //
  83.     // parse the PCX file
  84.     //
  85.     pcx = (pcx_t *)raw;
  86.     raw = &pcx->data;
  87.  
  88.     if (pcx->manufacturer != 0x0a
  89.         || pcx->version != 5
  90.         || pcx->encoding != 1
  91.         || pcx->bits_per_pixel != 8
  92.         || pcx->xmax >= 640
  93.         || pcx->ymax >= 480)
  94.     {
  95.         Com_Printf ("Bad pcx file %s\n", filename);
  96.         FS_FreeFile (pcx);
  97.         return;
  98.     }
  99.  
  100.     out = Z_Malloc ( (pcx->ymax+1) * (pcx->xmax+1) );
  101.  
  102.     *pic = out;
  103.  
  104.     pix = out;
  105.  
  106.     if (palette)
  107.     {
  108.         *palette = Z_Malloc(768);
  109.         memcpy (*palette, (byte *)pcx + len - 768, 768);
  110.     }
  111.  
  112.     if (width)
  113.         *width = pcx->xmax+1;
  114.     if (height)
  115.         *height = pcx->ymax+1;
  116.  
  117.     for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1)
  118.     {
  119.         for (x=0 ; x<=pcx->xmax ; )
  120.         {
  121.             dataByte = *raw++;
  122.  
  123.             if((dataByte & 0xC0) == 0xC0)
  124.             {
  125.                 runLength = dataByte & 0x3F;
  126.                 dataByte = *raw++;
  127.             }
  128.             else
  129.                 runLength = 1;
  130.  
  131.             while(runLength-- > 0)
  132.                 pix[x++] = dataByte;
  133.         }
  134.  
  135.     }
  136.  
  137.     if ( raw - (byte *)pcx > len)
  138.     {
  139.         Com_Printf ("PCX file %s was malformed", filename);
  140.         Z_Free (*pic);
  141.         *pic = NULL;
  142.     }
  143.  
  144.     FS_FreeFile (pcx);
  145. }
  146.  
  147. //=============================================================
  148.  
  149. /*
  150. ==================
  151. SCR_StopCinematic
  152. ==================
  153. */
  154. void SCR_StopCinematic (void)
  155. {
  156.     cl.cinematictime = 0;    // done
  157.     if (cin.pic)
  158.     {
  159.         Z_Free (cin.pic);
  160.         cin.pic = NULL;
  161.     }
  162.     if (cin.pic_pending)
  163.     {
  164.         Z_Free (cin.pic_pending);
  165.         cin.pic_pending = NULL;
  166.     }
  167.     if (cl.cinematicpalette_active)
  168.     {
  169.         R_SetPalette(NULL);
  170.         cl.cinematicpalette_active = false;
  171.     }
  172.     if (cl.cinematic_file)
  173.     {
  174.         fclose (cl.cinematic_file);
  175.         cl.cinematic_file = NULL;
  176.     }
  177.     if (cin.hnodes1)
  178.     {
  179.         Z_Free (cin.hnodes1);
  180.         cin.hnodes1 = NULL;
  181.     }
  182.  
  183.     // switch back down to 11 khz sound if necessary
  184.     if (cin.restart_sound)
  185.     {
  186.         cin.restart_sound = false;
  187.         CL_Snd_Restart_f ();
  188.     }
  189.  
  190. }
  191.  
  192. /*
  193. ====================
  194. SCR_FinishCinematic
  195.  
  196. Called when either the cinematic completes, or it is aborted
  197. ====================
  198. */
  199. void SCR_FinishCinematic (void)
  200. {
  201.     // tell the server to advance to the next map / cinematic
  202.     MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
  203.     SZ_Print (&cls.netchan.message, va("nextserver %i\n", cl.servercount));
  204. }
  205.  
  206. //==========================================================================
  207.  
  208. /*
  209. ==================
  210. SmallestNode1
  211. ==================
  212. */
  213. int    SmallestNode1 (int numhnodes)
  214. {
  215.     int        i;
  216.     int        best, bestnode;
  217.  
  218.     best = 99999999;
  219.     bestnode = -1;
  220.     for (i=0 ; i<numhnodes ; i++)
  221.     {
  222.         if (cin.h_used[i])
  223.             continue;
  224.         if (!cin.h_count[i])
  225.             continue;
  226.         if (cin.h_count[i] < best)
  227.         {
  228.             best = cin.h_count[i];
  229.             bestnode = i;
  230.         }
  231.     }
  232.  
  233.     if (bestnode == -1)
  234.         return -1;
  235.  
  236.     cin.h_used[bestnode] = true;
  237.     return bestnode;
  238. }
  239.  
  240.  
  241. /*
  242. ==================
  243. Huff1TableInit
  244.  
  245. Reads the 64k counts table and initializes the node trees
  246. ==================
  247. */
  248. void Huff1TableInit (void)
  249. {
  250.     int        prev;
  251.     int        j;
  252.     int        *node, *nodebase;
  253.     byte    counts[256];
  254.     int        numhnodes;
  255.  
  256.     cin.hnodes1 = Z_Malloc (256*256*2*4);
  257.     memset (cin.hnodes1, 0, 256*256*2*4);
  258.  
  259.     for (prev=0 ; prev<256 ; prev++)
  260.     {
  261.         memset (cin.h_count,0,sizeof(cin.h_count));
  262.         memset (cin.h_used,0,sizeof(cin.h_used));
  263.  
  264.         // read a row of counts
  265.         FS_Read (counts, sizeof(counts), cl.cinematic_file);
  266.         for (j=0 ; j<256 ; j++)
  267.             cin.h_count[j] = counts[j];
  268.  
  269.         // build the nodes
  270.         numhnodes = 256;
  271.         nodebase = cin.hnodes1 + prev*256*2;
  272.  
  273.         while (numhnodes != 511)
  274.         {
  275.             node = nodebase + (numhnodes-256)*2;
  276.  
  277.             // pick two lowest counts
  278.             node[0] = SmallestNode1 (numhnodes);
  279.             if (node[0] == -1)
  280.                 break;    // no more
  281.  
  282.             node[1] = SmallestNode1 (numhnodes);
  283.             if (node[1] == -1)
  284.                 break;
  285.  
  286.             cin.h_count[numhnodes] = cin.h_count[node[0]] + cin.h_count[node[1]];
  287.             numhnodes++;
  288.         }
  289.  
  290.         cin.numhnodes1[prev] = numhnodes-1;
  291.     }
  292. }
  293.  
  294. /*
  295. ==================
  296. Huff1Decompress
  297. ==================
  298. */
  299. cblock_t Huff1Decompress (cblock_t in)
  300. {
  301.     byte        *input;
  302.     byte        *out_p;
  303.     int            nodenum;
  304.     int            count;
  305.     cblock_t    out;
  306.     int            inbyte;
  307.     int            *hnodes, *hnodesbase;
  308. //int        i;
  309.  
  310.     // get decompressed count
  311.     count = in.data[0] + (in.data[1]<<8) + (in.data[2]<<16) + (in.data[3]<<24);
  312.     input = in.data + 4;
  313.     out_p = out.data = Z_Malloc (count);
  314.  
  315.     // read bits
  316.  
  317.     hnodesbase = cin.hnodes1 - 256*2;    // nodes 0-255 aren't stored
  318.  
  319.     hnodes = hnodesbase;
  320.     nodenum = cin.numhnodes1[0];
  321.     while (count)
  322.     {
  323.         inbyte = *input++;
  324.         //-----------
  325.         if (nodenum < 256)
  326.         {
  327.             hnodes = hnodesbase + (nodenum<<9);
  328.             *out_p++ = nodenum;
  329.             if (!--count)
  330.                 break;
  331.             nodenum = cin.numhnodes1[nodenum];
  332.         }
  333.         nodenum = hnodes[nodenum*2 + (inbyte&1)];
  334.         inbyte >>=1;
  335.         //-----------
  336.         if (nodenum < 256)
  337.         {
  338.             hnodes = hnodesbase + (nodenum<<9);
  339.             *out_p++ = nodenum;
  340.             if (!--count)
  341.                 break;
  342.             nodenum = cin.numhnodes1[nodenum];
  343.         }
  344.         nodenum = hnodes[nodenum*2 + (inbyte&1)];
  345.         inbyte >>=1;
  346.         //-----------
  347.         if (nodenum < 256)
  348.         {
  349.             hnodes = hnodesbase + (nodenum<<9);
  350.             *out_p++ = nodenum;
  351.             if (!--count)
  352.                 break;
  353.             nodenum = cin.numhnodes1[nodenum];
  354.         }
  355.         nodenum = hnodes[nodenum*2 + (inbyte&1)];
  356.         inbyte >>=1;
  357.         //-----------
  358.         if (nodenum < 256)
  359.         {
  360.             hnodes = hnodesbase + (nodenum<<9);
  361.             *out_p++ = nodenum;
  362.             if (!--count)
  363.                 break;
  364.             nodenum = cin.numhnodes1[nodenum];
  365.         }
  366.         nodenum = hnodes[nodenum*2 + (inbyte&1)];
  367.         inbyte >>=1;
  368.         //-----------
  369.         if (nodenum < 256)
  370.         {
  371.             hnodes = hnodesbase + (nodenum<<9);
  372.             *out_p++ = nodenum;
  373.             if (!--count)
  374.                 break;
  375.             nodenum = cin.numhnodes1[nodenum];
  376.         }
  377.         nodenum = hnodes[nodenum*2 + (inbyte&1)];
  378.         inbyte >>=1;
  379.         //-----------
  380.         if (nodenum < 256)
  381.         {
  382.             hnodes = hnodesbase + (nodenum<<9);
  383.             *out_p++ = nodenum;
  384.             if (!--count)
  385.                 break;
  386.             nodenum = cin.numhnodes1[nodenum];
  387.         }
  388.         nodenum = hnodes[nodenum*2 + (inbyte&1)];
  389.         inbyte >>=1;
  390.         //-----------
  391.         if (nodenum < 256)
  392.         {
  393.             hnodes = hnodesbase + (nodenum<<9);
  394.             *out_p++ = nodenum;
  395.             if (!--count)
  396.                 break;
  397.             nodenum = cin.numhnodes1[nodenum];
  398.         }
  399.         nodenum = hnodes[nodenum*2 + (inbyte&1)];
  400.         inbyte >>=1;
  401.         //-----------
  402.         if (nodenum < 256)
  403.         {
  404.             hnodes = hnodesbase + (nodenum<<9);
  405.             *out_p++ = nodenum;
  406.             if (!--count)
  407.                 break;
  408.             nodenum = cin.numhnodes1[nodenum];
  409.         }
  410.         nodenum = hnodes[nodenum*2 + (inbyte&1)];
  411.         inbyte >>=1;
  412.     }
  413.  
  414.     if (input - in.data != in.count && input - in.data != in.count+1)
  415.     {
  416.         Com_Printf ("Decompression overread by %i", (input - in.data) - in.count);
  417.     }
  418.     out.count = out_p - out.data;
  419.  
  420.     return out;
  421. }
  422.  
  423. /*
  424. ==================
  425. SCR_ReadNextFrame
  426. ==================
  427. */
  428. byte *SCR_ReadNextFrame (void)
  429. {
  430.     int        r;
  431.     int        command;
  432.     byte    samples[22050/14*4];
  433.     byte    compressed[0x20000];
  434.     int        size;
  435.     byte    *pic;
  436.     cblock_t    in, huf1;
  437.     int        start, end, count;
  438.  
  439.     // read the next frame
  440.     r = fread (&command, 4, 1, cl.cinematic_file);
  441.     if (r == 0)        // we'll give it one more chance
  442.         r = fread (&command, 4, 1, cl.cinematic_file);
  443.  
  444.     if (r != 1)
  445.         return NULL;
  446.     command = LittleLong(command);
  447.     if (command == 2)
  448.         return NULL;    // last frame marker
  449.  
  450.     if (command == 1)
  451.     {    // read palette
  452.         FS_Read (cl.cinematicpalette, sizeof(cl.cinematicpalette), cl.cinematic_file);
  453.         cl.cinematicpalette_active=0;    // dubious....  exposes an edge case
  454.     }
  455.  
  456.     // decompress the next frame
  457.     FS_Read (&size, 4, cl.cinematic_file);
  458.     size = LittleLong(size);
  459.     if (size > sizeof(compressed) || size < 1)
  460.         Com_Error (ERR_DROP, "Bad compressed frame size");
  461.     FS_Read (compressed, size, cl.cinematic_file);
  462.  
  463.     // read sound
  464.     start = cl.cinematicframe*cin.s_rate/14;
  465.     end = (cl.cinematicframe+1)*cin.s_rate/14;
  466.     count = end - start;
  467.  
  468.     FS_Read (samples, count*cin.s_width*cin.s_channels, cl.cinematic_file);
  469.  
  470.     S_RawSamples (count, cin.s_rate, cin.s_width, cin.s_channels, samples);
  471.  
  472.     in.data = compressed;
  473.     in.count = size;
  474.  
  475.     huf1 = Huff1Decompress (in);
  476.  
  477.     pic = huf1.data;
  478.  
  479.     cl.cinematicframe++;
  480.  
  481.     return pic;
  482. }
  483.  
  484.  
  485. /*
  486. ==================
  487. SCR_RunCinematic
  488.  
  489. ==================
  490. */
  491. void SCR_RunCinematic (void)
  492. {
  493.     int        frame;
  494.  
  495.     if (cl.cinematictime <= 0)
  496.     {
  497.         SCR_StopCinematic ();
  498.         return;
  499.     }
  500.  
  501.     if (cl.cinematicframe == -1)
  502.         return;        // static image
  503.  
  504.     if (cls.key_dest != key_game)
  505.     {    // pause if menu or console is up
  506.         cl.cinematictime = cls.realtime - cl.cinematicframe*1000/14;
  507.         return;
  508.     }
  509.  
  510.     frame = (cls.realtime - cl.cinematictime)*14.0/1000;
  511.     if (frame <= cl.cinematicframe)
  512.         return;
  513.     if (frame > cl.cinematicframe+1)
  514.     {
  515.         Com_Printf ("Dropped frame: %i > %i\n", frame, cl.cinematicframe+1);
  516.         cl.cinematictime = cls.realtime - cl.cinematicframe*1000/14;
  517.     }
  518.     if (cin.pic)
  519.         Z_Free (cin.pic);
  520.     cin.pic = cin.pic_pending;
  521.     cin.pic_pending = NULL;
  522.     cin.pic_pending = SCR_ReadNextFrame ();
  523.     if (!cin.pic_pending)
  524.     {
  525.         SCR_StopCinematic ();
  526.         SCR_FinishCinematic ();
  527.         cl.cinematictime = 1;    // hack to get the black screen behind loading
  528.         SCR_BeginLoadingPlaque ();
  529.         cl.cinematictime = 0;
  530.         return;
  531.     }
  532. }
  533.  
  534. /*
  535. ==================
  536. SCR_DrawCinematic
  537.  
  538. Returns true if a cinematic is active, meaning the view rendering
  539. should be skipped
  540. ==================
  541. */
  542. qboolean SCR_DrawCinematic (void)
  543. {
  544.     if (cl.cinematictime <= 0)
  545.     {
  546.         return false;
  547.     }
  548.  
  549.     if (cls.key_dest == key_menu)
  550.     {    // blank screen and pause if menu is up
  551.         R_SetPalette(NULL);
  552.         cl.cinematicpalette_active = false;
  553.         return true;
  554.     }
  555.  
  556.     if (!cl.cinematicpalette_active)
  557.     {
  558.         R_SetPalette(cl.cinematicpalette);
  559.         cl.cinematicpalette_active = true;
  560.     }
  561.  
  562.     if (!cin.pic)
  563.         return true;
  564.  
  565.     Draw_StretchRaw (0, 0, viddef.width, viddef.height,
  566.         cin.width, cin.height, cin.pic);
  567.  
  568.     return true;
  569. }
  570.  
  571. /*
  572. ==================
  573. SCR_PlayCinematic
  574.  
  575. ==================
  576. */
  577. void SCR_PlayCinematic (char *arg)
  578. {
  579.     int        width, height;
  580.     byte    *palette;
  581.     char    name[MAX_OSPATH], *dot;
  582.     int        old_khz;
  583.  
  584.     // make sure CD isn't playing music
  585.     CDAudio_Stop();
  586.  
  587.     cl.cinematicframe = 0;
  588.     dot = strstr (arg, ".");
  589.     if (dot && !strcmp (dot, ".pcx"))
  590.     {    // static pcx image
  591.         Com_sprintf (name, sizeof(name), "pics/%s", arg);
  592.         SCR_LoadPCX (name, &cin.pic, &palette, &cin.width, &cin.height);
  593.         cl.cinematicframe = -1;
  594.         cl.cinematictime = 1;
  595.         SCR_EndLoadingPlaque ();
  596.         cls.state = ca_active;
  597.         if (!cin.pic)
  598.         {
  599.             Com_Printf ("%s not found.\n", name);
  600.             cl.cinematictime = 0;
  601.         }
  602.         else
  603.         {
  604.             memcpy (cl.cinematicpalette, palette, sizeof(cl.cinematicpalette));
  605.             Z_Free (palette);
  606.         }
  607.         return;
  608.     }
  609.  
  610.     Com_sprintf (name, sizeof(name), "video/%s", arg);
  611.     FS_FOpenFile (name, &cl.cinematic_file);
  612.     if (!cl.cinematic_file)
  613.     {
  614. //        Com_Error (ERR_DROP, "Cinematic %s not found.\n", name);
  615.         SCR_FinishCinematic ();
  616.         cl.cinematictime = 0;    // done
  617.         return;
  618.     }
  619.  
  620.     SCR_EndLoadingPlaque ();
  621.  
  622.     cls.state = ca_active;
  623.  
  624.     FS_Read (&width, 4, cl.cinematic_file);
  625.     FS_Read (&height, 4, cl.cinematic_file);
  626.     cin.width = LittleLong(width);
  627.     cin.height = LittleLong(height);
  628.  
  629.     FS_Read (&cin.s_rate, 4, cl.cinematic_file);
  630.     cin.s_rate = LittleLong(cin.s_rate);
  631.     FS_Read (&cin.s_width, 4, cl.cinematic_file);
  632.     cin.s_width = LittleLong(cin.s_width);
  633.     FS_Read (&cin.s_channels, 4, cl.cinematic_file);
  634.     cin.s_channels = LittleLong(cin.s_channels);
  635.  
  636.     Huff1TableInit ();
  637.  
  638.     // switch up to 22 khz sound if necessary
  639.     old_khz = Cvar_VariableValue ("s_khz");
  640.     if (old_khz != cin.s_rate/1000)
  641.     {
  642.         cin.restart_sound = true;
  643.         Cvar_SetValue ("s_khz", cin.s_rate/1000);
  644.         CL_Snd_Restart_f ();
  645.         Cvar_SetValue ("s_khz", old_khz);
  646.     }
  647.  
  648.     cl.cinematicframe = 0;
  649.     cin.pic = SCR_ReadNextFrame ();
  650.     cl.cinematictime = Sys_Milliseconds ();
  651. }
  652.